package com.example.exceldemo.service.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import cn.hutool.core.lang.Dict;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import com.alibaba.excel.util.ListUtils;
import com.example.exceldemo.config.WordUtil;
import com.example.exceldemo.entity.HighPerson;
import com.example.exceldemo.entity.OrderBoomGetVo;
import com.example.exceldemo.enuns.FileType;
import com.example.exceldemo.exception.ServiceException;
import com.example.exceldemo.service.PdfService;
import com.example.exceldemo.utils.FileUtils;
import com.example.exceldemo.utils.PdfUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.lowagie.text.pdf.BaseFont;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description
 * @Author xiaohuang
 * @Date 2024/7/10
 */
@Slf4j
@Service
public class PdfServiceImpl implements PdfService {

    @Autowired
    private WordUtil wordUtil;
    private static final String TEMPLATE_PATH = "template/html";

    @Override
    public void exportTemplate() {
        String realImagePath = "E:/data/file/faceimg/tmp/1.jpg";
        //存放普通文字类
        Map<String, Object> data = new HashMap<>(15);
        String name = "小杨";
        data.put("name", name);
        data.put("age", 38);
        data.put("address", "北京市");
        data.put("sexual", "女生");
        data.put("love", "开朗");
        data.put("sex", "男");
        data.put("hight", "190cm");
        data.put("phone", "110");
        //处理图片路径
        HashMap<String, byte[]> map1 = new HashMap<>();
        byte[] aByte = FileUtils.getByte(realImagePath);
        //将图片添加进去
        map1.put("image", aByte);
        byte[] bytes = PdfUtil.generatePdfToLocal(data, map1, "/template/pdf/person3.pdf");
        PdfUtil.createPdf(bytes, name + "男嘉宾个人资料");

    }

    @Override
    public void exportPdf() {
        float lineHeight1 = (float) 25.0;
        float lineHeight2 = (float) 25.0;
        Document pdfDoc = null;
        PdfWriter writer = null;
        try {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            // 指定解析器
            System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
            String filename = "test.pdf";
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(filename, "UTF-8"));
            //新建document对象
            pdfDoc = new Document(PageSize.A4.rotate(), 36, 36, 24, 36);
            // 构造好的pdf文件输出位置
            String realImagePath = "E:/data/file/faceimg/tmp/1.jpg";

            writer = PdfWriter.getInstance(pdfDoc, response.getOutputStream());
            //打开pdf文件---注：只有document 打开后，才能往文件内写入导出信息
            pdfDoc.open();

            //PDFTable类似于html的表格文件，但是只有列的概念，定义列的数量，不能定义行的数量。
            //创建一个两列的表格
            PdfPTable headerTable = new PdfPTable(2);
            headerTable.setWidthPercentage(40);

            //3、创建左边数据表格PdfPTable iTable，划分为N列

            PdfPTable leftTable = new PdfPTable(4);//创建左边表格
            //4、往左边表格中写入数据，加入iTable中
            //4-1表格中可以合并单元格
            PdfPCell leftCell = new PdfPCell(new Paragraph("Hello"));
            leftCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            leftCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            leftCell.setFixedHeight(lineHeight1);
            leftCell.setColspan(4);
            leftTable.addCell(leftCell);
            //4-2填充数据
            for (int i = 0; i < 24; i++) {
                leftCell = new PdfPCell(new Paragraph("data"));
                leftCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                leftCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                leftCell.setFixedHeight(lineHeight2);
                leftTable.addCell(leftCell);
            }
            //将表格加入到第一列中
            PdfPCell cell = new PdfPCell(leftTable);
            cell.setPadding(0);
            headerTable.addCell(cell);

            //5、创建图片对象,加入headerTable中,此处写入图片路径
            Image image = Image.getInstance(realImagePath);
            // image.scaleAbsolute(5,5);//自定义大小
            // image.scalePercent(50);//缩放百分比 --- 测试不起作用
            image.scaleToFit(250, 250);//自定义大小
            PdfPCell acell = new PdfPCell(image, false);
            headerTable.addCell(acell);
            //将主要的表格headerTable加入document文档对象中
            pdfDoc.add(headerTable);
            //关闭文档对象，注：当文档对象真正关闭后，数据才会写入文件中。
            pdfDoc.close();

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (pdfDoc != null) {
                pdfDoc.close();
            }
            if (writer != null) {
                writer.close();
            }
        }


    }

    @Override
    public void exportWordToPdf() {
        String realImagePath="E:/data/file/faceimg/tmp/1.jpg";
        //存放单个数据
        HashMap<String, Object> mapHead = new HashMap<>();
        mapHead.put("tile", "深圳程序猿相亲记");
        mapHead.put("age", "23");
        mapHead.put("name", "隔壁小王");
        //创建了一个名为simage的新的ImageEntity对象，并将其赋值给simage变量。
        // 具体来说，ImageEntity是一个Java类，用于表示一个图像实体，其中包含了图像的各种属性和数据。
        ImageEntity simage = new ImageEntity();
        simage.setHeight(80);
        simage.setWidth(80);
        simage.setType(ImageEntity.Data);
        simage.setData(FileUtils.getByte(realImagePath)); //字节流读取
        //将图片添加进去
        mapHead.put("image", simage);
        List<Map<String, Object>> alarms = new ArrayList<>();
        //存放表头
        for (int i = 0; i <10 ; i++) {
            Map<String, Object> alarm=new HashMap<>();
            alarm.put("order","男嘉宾"+i+"号");
            alarm.put("name","小鱼"+i);
            alarm.put("age",18+i);
            alarm.put("image",simage);
            alarm.put("optimal","能吃");
            alarms.add(alarm);
        }
        mapHead.put("alarms", alarms);
        byte[] bytes = wordUtil.exportPdfByte("template/word/jxxj.docx", mapHead, "jxxj.docx");
        FileUtils.exportByte(bytes, "深圳相亲记", FileType.PDF);

    }

    @Override
    public void initExportPdf() {
        Document document = null;
        PdfWriter writer = null;
        try {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            // 指定解析器
            System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
            String filename = "test.pdf";
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(filename, "UTF-8"));
            //生成文档对象
            //设置中文字体
            com.itextpdf.text.pdf.BaseFont bfChinese = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
            Font fontChinese = new Font(bfChinese, 10.5F, Font.NORMAL);// 五号

            document = new Document();
            writer = PdfWriter.getInstance(document, response.getOutputStream());
            document.open();

            com.itextpdf.text.pdf.BaseFont bfChinese1 = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
            Font fontChineseTitles = new Font(bfChinese1, 20F, Font.NORMAL);// 五号
            Font fontChineseTitle = new Font(bfChinese1, 14F, Font.NORMAL);// 五号

            PdfPTable tableBox = new PdfPTable(22);
            tableBox.setWidths(new float[]{0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f});// 每个单元格占多宽
            tableBox.setWidthPercentage(100f);
            // 创建表格格式及内容
            tableBox.addCell(getCell(new Phrase("测试pdf标题头", fontChineseTitles), 40f, 22, 1, true, true, 15));


            tableBox.addCell(getCell(new Phrase("主题", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("测试主题内容", fontChinese), 25f, 18, 1, true, true));

            tableBox.addCell(getCell(new Phrase("项目名称", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("测试项目名称", fontChinese), 25f, 18, 1, true, true));

            tableBox.addCell(getCell(new Phrase("入行日期", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("2024-12-31", fontChinese), 25f, 7, 1, true, true));

            tableBox.addCell(getCell(new Phrase("交货日期", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("2024-12-31", fontChinese), 25f, 7, 1, true, true));

            tableBox.addCell(getCell(new Phrase("编号", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("23333No111", fontChinese), 25f, 7, 1, true, true));


            tableBox.addCell(getCell(new Phrase("总额", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase(2000 + "", fontChinese), 25f, 7, 1, true, true));
            String remarkTest = "1276555555555555555555555555555555555522222222222222222换行测试222222222222222222222222222222222222222222222222222222";

            tableBox.addCell(getCell(new Phrase("说明", fontChinese), 50f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase(remarkTest, setFontSize(remarkTest)), 50f, 18, 1, true, true));
            tableBox.addCell(getCell(new Phrase("说明2", fontChinese), 50f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase(remarkTest, setFontSize(remarkTest)), 50f, 18, 1, true, true));

            tableBox.addCell(getCell(new Phrase("物品信息-表单标题", fontChineseTitle), 30f, 22, 1, true, true));
            tableBox.addCell(getCell(new Phrase("序号", fontChinese), 25f, 2, 1, true, true));
            tableBox.addCell(getCell(new Phrase("名称", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("型号", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("规格", fontChinese), 25f, 4, 1, true, true));
            tableBox.addCell(getCell(new Phrase("备注", fontChinese), 25f, 7, 1, true, true));
            tableBox.addCell(getCell(new Phrase("图片", fontChinese), 25f, 1, 1, true, true));

            List<OrderBoomGetVo> orderBoomList = selectList();
            String realImagePath = "E:/data/file/faceimg/tmp/3.jpg";

            if (!CollectionUtils.isEmpty(orderBoomList)) {
                for (int i = 0; i < orderBoomList.size(); i++) {
                    String model = orderBoomList.get(i).getModel(); //型号
                    String specifications = orderBoomList.get(i).getSpecifications(); //规格参数
                    String remark = orderBoomList.get(i).getRemark(); //备注
                    float modelHeight = setModelOrSpecificationsHeight(model, "model");
                    float specificationsHeight = setModelOrSpecificationsHeight(specifications, "specifications");
                    float remarkHeight = setModelOrSpecificationsHeight(remark, "remark");
                    float finalHeight = Math.max((Math.max(modelHeight, specificationsHeight)), remarkHeight);
                    if (modelHeight == 0 && specificationsHeight == 0 && remarkHeight == 0) {
                        finalHeight = 45f;
                    }

                    //序号
                    tableBox.addCell(getCell(new Phrase(i + 1 + "", fontChinese), finalHeight, 2, 1, true, false));
                    //名称
                    tableBox.addCell(getCell(new Phrase(StringUtils.isEmpty(orderBoomList.get(i).getBoomName()) ? "" : orderBoomList.get(i).getBoomName(), fontChinese), finalHeight, 4, 1, true, false));
                    //型号
                    tableBox.addCell(getCell(new Phrase(StringUtils.isEmpty(orderBoomList.get(i).getModel()) ? "" : orderBoomList.get(i).getModel(), fontChinese), finalHeight, 4, 1, true, false));
                    //规格
                    tableBox.addCell(getCell(new Phrase((StringUtils.isEmpty(orderBoomList.get(i).getSpecifications()) ? "" : orderBoomList.get(i).getSpecifications()), fontChinese), finalHeight, 4, 1, true, false));
                    //备注
                    tableBox.addCell(getCell(new Phrase(StringUtils.isEmpty(orderBoomList.get(i).getRemark()) ? "" : orderBoomList.get(i).getRemark(), fontChinese), finalHeight, 7, 1, true, false));
                    //5、创建图片对象,加入headerTable中,此处可写入图片路径或字节数组
                    Image image = Image.getInstance(realImagePath);
                    // image.scaleAbsolute(5,5);//自定义大小
                    // image.scalePercent(50);//缩放百分比 --- 测试不起作用
                    image.scaleToFit(50, 50);//自定义大小
                    PdfPCell acell = new PdfPCell(image, false);
                    tableBox.addCell(acell);
                }
            }
            document.add(tableBox);
            // document.newPage();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            if (document != null) {
                document.close();
            }
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 将HTML导出到PDF
     * 该方法主要负责将一个HTML模板渲染成带数据的HTML字符串，并将其转换为PDF格式
     */
    @Override
    public void exportHtmlToPdf() {
        try {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            FileUtils.setContentType(response, "测试html转pdf", FileType.PDF);
            // 获取HTML模板引擎
            TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig(TEMPLATE_PATH, TemplateConfig.ResourceMode.CLASSPATH));
            // 加载HTML模板文件
            Template template = engine.getTemplate("test.html");

            // 创建数据字典，用于填充模板中的变量
            Dict dict = Dict.create();
            dict.set("name", "测试导出模版标题");
            dict.set("meetingDate", "2024");
            dict.set("address", "广东省深圳市");
            dict.set("compereName", "哈哈哈公司");
            dict.set("lastTempDays", 1);
            dict.set("lastRainDays", 2);
            dict.set("lastWindDays", 3);
            dict.set("lastMeetingType", "上周");
            // 设置模板内容，此处为富文本内容
            dict.set("content", "<span style='color: #ff0000;'>测试模版内容哈</span>");
            // 渲染模板，生成HTML字符串
            String html = template.render(dict);
            try (ByteArrayOutputStream byteOs = new ByteArrayOutputStream()) {
                // 创建 ITextRenderer 对象用于HTML到PDF的转换
                ITextRenderer renderer = new ITextRenderer();
                // 获取字体解析器，以便添加中文字体支持
                ITextFontResolver fontResolver = (ITextFontResolver) renderer.getSharedContext().getFontResolver();
                // 添加中文字体，为了在PDF中支持中文显示
                fontResolver.addFont(getFontPath("FangSong_GB2312",Boolean.TRUE), "FangSong_GB2312", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, "");
                fontResolver.addFont(getFontPath("simsun",Boolean.FALSE), "Song", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, "");
                // 设置为文档内容
                renderer.setDocumentFromString(html);
                // 布局文档
                renderer.layout();
                renderer.createPDF(byteOs);
                renderer.finishPDF();
                try (ServletOutputStream os = response.getOutputStream()) {
                    os.write(byteOs.toByteArray());
                    os.flush();
                }
            }
        } catch (IOException e) {
            log.error("html转pdf异常：" + e.getMessage());
            throw new ServiceException("html转pdf异常：" + e.getMessage());
        }
    }


    private List<OrderBoomGetVo> selectList() {
        ArrayList<OrderBoomGetVo> vos = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            OrderBoomGetVo vo = new OrderBoomGetVo();
            vo.setBoomName(" 我是猪" + i);
            vo.setModel("型号" + i);
            vo.setRemark("备注哈哈哈" + i);
            vo.setSpecifications("规格" + i);
            vos.add(vo);
        }
        return vos;
    }

    private float setModelOrSpecificationsHeight(String argName, String name) throws DocumentException, IOException {
        if (StringUtils.isEmpty(argName)) {
            return 0;
        }
        String replace = argName.replaceAll("\\r?\\n", "");
        com.itextpdf.text.pdf.BaseFont baseFont = com.itextpdf.text.pdf.BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
        float fontSize = 10.5f;
        float height = 25f;
        /*baseFont渲染后的文字宽度*/
        float textWidth = baseFont.getWidthPoint(replace, fontSize);

        //文本区的行宽
        float textBoxWidth;

        if (name.equals("remark")) {
            textBoxWidth = 5.65f;
        } else {
            textBoxWidth = 6f;
        }

        /*文本单行行高*/
        float ascent = baseFont.getFontDescriptor(baseFont.ASCENT, fontSize);

        //文本占几行f
        float v = textWidth / textBoxWidth;

        //文本渲染所占大小
        float text = v * ascent;
        /*文本框高度只够写一行，并且文字宽度大于文本框宽度，则缩小字体*/
        while (height * textBoxWidth < v * ascent) {
            height += 0.125;
        }
        return height;
    }

    private Font setFontSize(String str) throws DocumentException, IOException {
        float size = checkAddrLength(str, 50f, 18f);
        com.itextpdf.text.pdf.BaseFont bfChinese = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese, size, Font.NORMAL);// 五号
        return fontChinese;
    }

    public float checkAddrLength(String addr, float textBoxHeight, float textBoxWidth) throws IOException, DocumentException {
        com.itextpdf.text.pdf.BaseFont baseFont = com.itextpdf.text.pdf.BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.NOT_EMBEDDED);
        float fontSize = 10.5f;

        /*baseFont渲染后的文字宽度*/
        float textWidth = baseFont.getWidthPoint(addr, fontSize);

        /*文本单行行高*/
        float ascent = baseFont.getFontDescriptor(baseFont.ASCENT, fontSize);

        //文本占几行
        float v = textWidth / textBoxWidth;

        //文本渲染所占大小
        float text = v * ascent;

        /*文本框高度只够写一行，并且文字宽度大于文本框宽度，则缩小字体*/
        while (textBoxHeight * textBoxWidth < v * ascent) {
            fontSize -= 0.5;
            textWidth = baseFont.getWidthPoint(addr, fontSize);
            ascent = baseFont.getFontDescriptor(baseFont.ASCENT, fontSize);
            v = textWidth / textBoxWidth;
        }
        return fontSize;
    }

    public static PdfPCell getCell(Phrase phrase, float height, int colSpan, int rowSpan, boolean isHorizontalCenter, boolean isVerticalCenter, Integer size) {
        PdfPCell cells = new PdfPCell(phrase);
        cells.setUseAscender(true);
        cells.setHorizontalAlignment(isHorizontalCenter ? Element.ALIGN_CENTER : Element.ALIGN_LEFT);
        cells.setVerticalAlignment(isVerticalCenter ? Element.ALIGN_MIDDLE : Element.ALIGN_TOP);
        cells.setColspan(colSpan);
        cells.setRowspan(rowSpan);
        cells.setNoWrap(false);
        cells.setFixedHeight(height);
        cells.disableBorderSide(size);
        return cells;
    }

    public static PdfPCell getCell(Phrase phrase, float height, int colSpan, int rowSpan, boolean isHorizontalCenter, boolean isVerticalCenter) {
        PdfPCell cells = new PdfPCell(phrase);
        cells.setUseAscender(true);
        cells.setHorizontalAlignment(isHorizontalCenter ? Element.ALIGN_CENTER : Element.ALIGN_LEFT);
        cells.setVerticalAlignment(isVerticalCenter ? Element.ALIGN_MIDDLE : Element.ALIGN_TOP);
        cells.setColspan(colSpan);
        cells.setRowspan(rowSpan);
        cells.setNoWrap(false);
        cells.setFixedHeight(height);
        return cells;
    }

    private String getFontPath(String fontName, Boolean isTTF) {
        if (isTTF)
            return "/font/" + fontName + ".ttf";
        else
            return "/font/" + fontName + ".ttc";
    }


    public List<HighPerson> date2() {
        List<HighPerson> list = ListUtils.newArrayList();
        for (int i = 0; i < 5; i++) {
            HighPerson fillData = new HighPerson();
            int num = i + 1;
            fillData.setNum(num);
            fillData.setName("张" + num);
            fillData.setAge(num);
            fillData.setAddress("地址" + num);
            list.add(fillData);
        }
        return list;
    }

}
